package com.mega.ycy.mixin;

import com.mega.ycy.Yiciyuan_EVENT;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityList;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.profiler.Profiler;
import net.minecraft.world.World;
import net.minecraft.world.WorldProvider;
import net.minecraft.world.WorldServer;
import net.minecraft.world.storage.ISaveHandler;
import net.minecraft.world.storage.WorldInfo;
import org.apache.logging.log4j.Logger;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;

import java.util.Map;
import java.util.UUID;

@Mixin(WorldServer.class)
public abstract class ServerWorldMixin extends World {
    @Shadow @Final private static Logger LOGGER;

    @Shadow public Map<UUID, Entity> entitiesByUuid;

    protected ServerWorldMixin(ISaveHandler saveHandlerIn, WorldInfo info, WorldProvider providerIn, Profiler profilerIn, boolean client) {
        super(saveHandlerIn, info, providerIn, profilerIn, client);
    }

    @Overwrite
    public boolean spawnEntity(Entity entityIn)
    {
        return this.canAddEntity(entityIn) && super.spawnEntity(entityIn);
    }

    @Overwrite
    public boolean canAddEntity(Entity entityIn)
    {
        if (Yiciyuan_EVENT.isDeath(entityIn))
            return false;
        if (entityIn.isDead)
        {
            LOGGER.warn("Tried to add entity {} but it was marked as removed already", (Object) EntityList.getKey(entityIn));
            return false;
        }
        else
        {
            UUID uuid = entityIn.getUniqueID();

            if (this.entitiesByUuid.containsKey(uuid))
            {
                Entity entity = this.entitiesByUuid.get(uuid);

                if (this.unloadedEntityList.contains(entity))
                {
                    this.unloadedEntityList.remove(entity);
                }
                else
                {
                    if (!(entityIn instanceof EntityPlayer))
                    {
                        LOGGER.warn("Keeping entity {} that already exists with UUID {}", EntityList.getKey(entity), uuid.toString());
                        return false;
                    }

                    LOGGER.warn("Force-added player with duplicate UUID {}", (Object)uuid.toString());
                }

                this.removeEntityDangerously(entity);
            }

            return true;
        }
    }

    @Overwrite
    public void onEntityAdded(Entity entityIn)
    {
        if (Yiciyuan_EVENT.isDeath(entityIn))
            return;
        super.onEntityAdded(entityIn);
        this.entitiesById.addKey(entityIn.getEntityId(), entityIn);
        this.entitiesByUuid.put(entityIn.getUniqueID(), entityIn);
        Entity[] aentity = entityIn.getParts();

        if (aentity != null)
        {
            for (Entity entity : aentity)
            {
                this.entitiesById.addKey(entity.getEntityId(), entity);
            }
        }
    }

    @Overwrite
    public void onEntityRemoved(Entity entityIn)
    {
        if (Yiciyuan_EVENT.isSafe(entityIn))
            return;
        super.onEntityRemoved(entityIn);
        this.entitiesById.removeObject(entityIn.getEntityId());
        this.entitiesByUuid.remove(entityIn.getUniqueID());
        Entity[] aentity = entityIn.getParts();

        if (aentity != null)
        {
            for (Entity entity : aentity)
            {
                this.entitiesById.removeObject(entity.getEntityId());
            }
        }
    }
}
